package org.dreamwork.jasmine2.restful.client.gui.ui;

import org.dreamwork.util.StringUtil;

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.*;

/**
 * Created by IntelliJ IDEA.
 * User: seth.yang
 * Date: 2014/12/11
 * Time: 19:15
 */
public class LogPane extends JTextPane implements MouseListener {
    private PrintStream out, err;
    private JMenuItem copy;

    private JPopupMenu menu;

    private static final int MAX_LINES = 20000;

    public LogPane () {
        super ();
        setEditable (false);

        MutableAttributeSet normal = new SimpleAttributeSet ();
        StyleConstants.setFontFamily (normal, "DialogInput");
        StyleConstants.setForeground (normal, Color.BLACK);
        StyleConstants.setFontSize (normal, 12);

        MutableAttributeSet warn = new SimpleAttributeSet ();
        StyleConstants.setFontFamily (warn, "DialogInput");
        StyleConstants.setForeground (warn, Color.RED);
        StyleConstants.setFontSize (warn, 12);

        out = new JTextPaneLoggerPrintStream (new ByteArrayOutputStream (1024), normal, this);
        err = new JTextPaneLoggerPrintStream (new ByteArrayOutputStream (1024), warn, this);

        setupMenu ();
        addMouseListener (this);

        setCursor (Cursor.getPredefinedCursor (Cursor.TEXT_CURSOR));
    }

    public PrintStream getOut () {
        return out;
    }

    public PrintStream getErr () {
        return err;
    }

    public void log (Object o) {
        out.println (o);
    }

    public void log (String message) {
        out.println (message);
    }

    public void warn (Object message) {
        err.println (message);
    }

    public void error (Object message) {
        err.println (message);
    }

    public void error (Object message, Throwable t) {
        err.println (message);
        t.printStackTrace (err);
    }

    public void clear () {
        try {
            StyledDocument doc = getStyledDocument ();
            doc.remove (0, doc.getLength ());
        } catch (BadLocationException e) {
            e.printStackTrace ();
        }
    }

    private void setupMenu () {
        menu = new JPopupMenu ();
        JMenuItem item = new JMenuItem ("Clear All");
        item.addActionListener (new ActionListener () {
            @Override
            public void actionPerformed (ActionEvent e) {
                clear ();
            }
        });
        menu.add (item);

        copy = new JMenuItem ("Copy");
        copy.addActionListener (new ActionListener () {
            @Override
            public void actionPerformed (ActionEvent e) {
                Clipboard clipboard = Toolkit.getDefaultToolkit ().getSystemClipboard ();
                String text = getSelectedText ();
                if (!StringUtil.isEmpty (text)) {
                    StringSelection selection = new StringSelection (text);
                    clipboard.setContents (selection, selection);
                }
            }
        });
        menu.add (copy);
    }

    @Override
    public void mouseClicked (MouseEvent e) {
        if (SwingUtilities.isRightMouseButton (e)) {
            String text = getSelectedText ();
            if (StringUtil.isEmpty (text)) {
                copy.setEnabled (false);
            } else {
                copy.setEnabled (true);
            }
            menu.show (this, e.getX (), e.getY ());
        }
    }

    @Override
    public void mousePressed (MouseEvent e) {

    }

    @Override
    public void mouseReleased (MouseEvent e) {

    }

    @Override
    public void mouseEntered (MouseEvent e) {

    }

    @Override
    public void mouseExited (MouseEvent e) {

    }

    public static class JTextPaneLoggerPrintStream extends PrintStream {
        static final Object locker = new Object ();
        ByteArrayOutputStream out;
        StyledDocument doc;
        MutableAttributeSet attr;
        JTextPane pane;

        public JTextPaneLoggerPrintStream (ByteArrayOutputStream out, MutableAttributeSet attr, JTextPane pane) {
            super (out, true);
            this.out = out;
            this.pane = pane;
            this.doc = pane.getStyledDocument ();
            this.attr = attr;
        }

        @Override
        public void write (byte[] buff, int off, int len) {
            super.write (buff, off, len);
            synchronized (locker) {
                String text = out.toString ();
                try {
                    doc.insertString (doc.getLength (), text, attr);
                    pane.setCaretPosition (doc.getLength ());
                    Element root = doc.getDefaultRootElement ();
                    int count = root.getElementCount ();
                    if (count > MAX_LINES) {
                        int offset = count - MAX_LINES;
                        Element e = root.getElement (offset);
                        if (e != null) {
                            doc.remove (0, e.getEndOffset ());
                        }
                    }
                } catch (BadLocationException e) {
                    //
                }
            }
            out.reset ();
        }
    }
}